import iotUtils
import ter
import time
import threading
class TBus645( ter.TIotBus):
    def __init__(self , ter ):
        super().__init__(ter)
        self.client = None

    def init (self):
        try: 
            super().init()
        except Exception as er:
            print(er)
    def isConnected (self):
        res = False
        try:
            if self.client and self.client.is_open :
                res = True
        except Exception as er:
            print(er)
        return res
    def start (self):
        try:
            print('start 645 client')
            comPort = self.busInfo['comPort']
            baudrate = self.busInfo['baudrate']
            parity = self.busInfo['parity']
            self.client = iotUtils.TIotUtils.getSerialClient( comPort , baudrate , parity)
            print(f'connect 645 serial port success.{comPort},{baudrate},{parity}.')
            self.running = True
            taskList = list(self.tasks.values())
            taskIndex = -1
            print(f'serial:{comPort} , tasks:{len(taskList)} , running:{self.running} , isConnected:{self.isConnected()}')
            while   len(taskList)>0  and  self.running and self.isConnected():
                try:
                    nowTm = time.time()
                    taskIndex = taskIndex + 1
                    if taskIndex>= len(taskList):
                        taskIndex = 0
                    task = taskList[taskIndex]
                    taskLastTime = task['lastTm']
                    frequency = task['frequency']
                    flag = nowTm - taskLastTime > frequency
                    if flag :
                        task['lastTm'] = nowTm

                        dataFlag = ('0000'+str(task['funCode']))[-4:]
                        address = ('000000000000'+ str(task['unitId']))[-12:]
                        sendBytes = self.getSendBytes(address,dataFlag)

                        self.client.write(sendBytes)
                        self.client.flush()
                        print(f'sendCmd:{[hex(x) for x in sendBytes]}')
                        time.sleep(5)
                        #print('send645',str(taskIndex), task['taskCode'],[hex(x) for x in sendBytes])
                        #self.client.flush()
                        recData = list(self.client.readall())
                        print(f'rec bytes({len(recData)}):{[hex(x) for  x in recData]}')
                        i = 0
                        resBytes = []
                        recFlag = False
                        while i < len(recData):
                            if recData[i] == 0x68:
                                resBytes = recData[i:]
                                recFlag = True
                                break
                            i = i + 1
                        if recFlag:
                            #print('rec 645 bytes:', resBytes)
                            minus = 0
                            resStr=""
                            endByte = resBytes[-3]
                            minusFlag = dataFlag in ['0122', '0222', '0322', '0032', '0042', '0062']
                            if minusFlag and endByte > 0x7f:
                                print('--------> minus endByte', endByte)
                                try:
                                    minus = 1
                                    endByte = endByte & 0x7f
                                    resBytes[-3] = endByte
                                except Exception as erMinus:
                                    print('minus error.', erMinus)
                            try:
                                dataBytes = ["{:0>2d}".format(int(hex(x - 0x33).replace('0x', ''))) for x in resBytes[14:-2]]
                                dataBytes.reverse()
                                resStr = "".join(dataBytes)
                            except Exception as erDeco:
                                print('-------------------  error  ------------------------------------')
                                print('645error','sendbytes', [hex(x) for x in sendBytes])
                                print('erDecode error', erDeco, [str(x) for x in resBytes])
                                print('---------------------------------------------------------')
                            if minus > 0:
                                resStr = str(-1 * int(resStr))
                            #registerBytes = [int(resStr)]
                            #registerBytes = int(resStr).to_bytes(4, byteorder='big')
                            registerBytes = [int(resStr)]
                            self.doOnTask(task , registerBytes)
                except Exception as eer:
                    print(eer)
        except Exception as er:
            print(er)
    def stop (self):
        try:
            if self.isConnected():
                self.client.close()
            self.client = None
        except Exception as er:
            print(er)
    def getSendBytes(self, address, dataFlag):
        res = []
        try:
            res.append(0x68)
            for i in range(6):
                pos = (6 - (i + 1)) * 2
                addr = int(address[pos:pos + 2])
                addr = (addr // 10) * 16 + addr % 10
                res.append(addr)
            res.append(0x68)
            res.append(0x11)
            res.append(0x04)
            for i in range(4):
                di = int(dataFlag[i]) + 0x33
                res.append(di)
            c = 0
            for i in res:
                c = c + i
                c = c % 256
            res.append(c)
            res.append(0x16)
        except Exception as er:
            print(er)
        return bytearray(res)

ter.iotTer.registBusType('645' , TBus645)